/* A simple server in the internet domain using TCP
 The port number is passed as an argument
 This version runs forever, forking off a separate
 process for each connection
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <fstream>

using namespace std;

void dostuff(int); /* function prototype */
socklen_t fromlen;
struct sockaddr_in server;
struct sockaddr_in from;
char buffer[256];

void error(const char *msg) {
	perror(msg);
	exit(1);
}

bool caseInsensitiveStringCompare(const string& str1, const string& str2) {
	if (str1.size() != str2.size()) {
		return false;
	}
	for (string::const_iterator c1 = str1.begin(), c2 = str2.begin();
			c1 != str1.end(); ++c1, ++c2) {
		if (tolower(*c1) != tolower(*c2)) {
			return false;
		}
	}
	return true;
}

bool is_file(string file_name) {
	string type = "";
	for (int var = file_name.length() - 1; var >= 0; --var) {
		if (file_name.at(var) == '.') {
			if (caseInsensitiveStringCompare(type, "html")
					|| caseInsensitiveStringCompare(type, "jpg")
					|| caseInsensitiveStringCompare(type, "png")
					|| caseInsensitiveStringCompare(type, "gif")
					|| caseInsensitiveStringCompare(type, "txt")) {
				return true;

			}
			return false;
		}
		type = file_name.at(var) + type;
	}
	return false;
}

int main(int argc, char *argv[]) {

	int sock,  length, n, pid;

	//char buf[1024];

	if (argc < 2) {
		fprintf(stderr, "ERROR, no port provided\n");
		exit(0);
	}

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0)
		error("Opening socket");
	length = sizeof(server);
	bzero(&server, length);
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(atoi(argv[1]));
	if (bind(sock, (struct sockaddr *) &server, length) < 0)
		error("binding");
	fromlen = sizeof(struct sockaddr_in);

	while (1) {
		bzero(buffer,256);
		n = recvfrom(sock, buffer, 1024, 0, (struct sockaddr *) &from, &fromlen);
		if (n < 0)error("recvfrom");
		cout<<"done1"<<endl;
		cout<<buffer<<endl;
		n = sendto(sock, "Got your message\n", 17, 0, (struct sockaddr *) &from,fromlen);
		cout<<n<<endl;
		if (n < 0)error("sendto");
		cout<<"done2"<<endl;
		dostuff (sock);
//		pid = fork();
//		if (pid < 0)
//			error("ERROR on fork");
//		if (pid == 0) {
//			close (sock);
//			dostuff (newsock);
//			exit(0);
//		} else
//			close (newsock);
	} /* end of while */
	close (sock);


return 0; /* we never get here */
}

void dostuff(int sock ) {
int n, n1;

cout<<"buffer before if"<<buffer<<endl;
vector<string> tokens;
istringstream iss(buffer);
copy(istream_iterator<string>(iss), istream_iterator<string>(),
		back_inserter<vector<string> >(tokens));
if (tokens.size() != 3 || tokens[0].compare("GET") != 0
		|| tokens[2].compare("HTTP/1.0") || !is_file(tokens[1]))
{
	cout<<"tokens size:"<<tokens.size()<<endl;
	//write(sock, "HTTP/1.0 ERROR\r\n", 16);
	n1 = sendto(sock, "HTTP/1.0 ERROR\r\n", 16, 0, (struct sockaddr *) &from,
			fromlen);
if (n1 < 0)error("sendto");
n1 = recvfrom(sock, buffer, 255, 0, (struct sockaddr *) &from, &fromlen);
if (n1 < 0)error("recvfrom");
}
else {
	FILE* fp = fopen(tokens[1].c_str(), "r");
	string message = "";
	if (fp == NULL) {
		message = "HTTP/1.0 404 Not Found\r\n";
		n1 = sendto(sock, message.c_str(), message.length(), 0,
				(struct sockaddr *) &from, fromlen);
		if (n1 < 0)
			error("sendto");
		n1 = recvfrom(sock, buffer, 255, 0, (struct sockaddr *) &from,
				&fromlen);
		if (n1 < 0)
			error("recvfrom");

	} else {
		message = "HTTP/1.0 200 OK\r\n";
		n1 = sendto(sock, message.c_str(), message.length(), 0,
				(struct sockaddr *) &from, fromlen);
		if (n1 < 0)
			error("sendto");
		n1 = recvfrom(sock, buffer, 255, 0, (struct sockaddr *) &from,
				&fromlen);
		if (n1 < 0)
			error("recvfrom");

		bzero(buffer, 256);
		while ((n = fread(buffer, sizeof(char), 255, fp)) > 0) {
			cout<<"packet sent"<<endl;
			cout<<buffer<<endl;
			sendto(sock, buffer, n, 0, (struct sockaddr *) &from, fromlen);
			n1 = recvfrom(sock, buffer, 255, 0, (struct sockaddr *) &from,
					&fromlen);
		}
		//send last packet
		bzero(buffer, 256);
		sendto(sock, buffer, n, 0, (struct sockaddr *) &from, fromlen);
		n1 = recvfrom(sock, buffer, 255, 0, (struct sockaddr *) &from,
							&fromlen);
	}
}
}
